#include "delay.h"
//////////////////////////////////////////////////////////////////////////////////
// �����Ҫʹ��OS,����������ͷ�ļ�����.
#if SYSTEM_SUPPORT_OS
#include "includes.h" //ucos ʹ��
#endif
//////////////////////////////////////////////////////////////////////////////////
// ������ֻ��ѧϰʹ�ã�δ���������ɣ��������������κ���;
// ALIENTEK STM32������
// ʹ��SysTick����ͨ����ģʽ���ӳٽ��й������ʺ�STM32F10xϵ�У�
// ����delay_us,delay_ms
// ����ԭ��@ALIENTEK
// ������̳:www.openedv.com
// ��������:2010/1/1
// �汾��V1.8
// ��Ȩ���У�����ؾ���
// Copyright(C) �������������ӿƼ����޹�˾ 2009-2019
// All rights reserved
//********************************************************************************
// V1.2�޸�˵��
// �������ж��е��ó�����ѭ���Ĵ���
// ��ֹ��ʱ��׼ȷ,����do while�ṹ!
// V1.3�޸�˵��
// �����˶�UCOSII��ʱ��֧��.
// ���ʹ��ucosII,delay_init���Զ�����SYSTICK��ֵ,ʹ֮��ucos��TICKS_PER_SEC��Ӧ.
// delay_ms��delay_usҲ���������ucos�ĸ���.
// delay_us������ucos��ʹ��,����׼ȷ�Ⱥܸ�,����Ҫ����û��ռ�ö���Ķ�ʱ��.
// delay_ms��ucos��,���Ե���OSTimeDly����,��δ����ucosʱ,������delay_usʵ��,�Ӷ�׼ȷ��ʱ
// ����������ʼ������,��������ucos֮��delay_ms������ʱ�ĳ���,ѡ��OSTimeDlyʵ�ֻ���delay_usʵ��.
// V1.4�޸�˵�� 20110929
// �޸���ʹ��ucos,����ucosδ������ʱ��,delay_ms���ж��޷���Ӧ��bug.
// V1.5�޸�˵�� 20120902
// ��delay_us����ucos��������ֹ����ucos���delay_us��ִ�У����ܵ��µ���ʱ��׼��
// V1.6�޸�˵�� 20150109
// ��delay_ms����OSLockNesting�жϡ�
// V1.7�޸�˵�� 20150319
// �޸�OS֧�ַ�ʽ,��֧������OS(������UCOSII��UCOSIII,����������OS������֧��)
// ����:delay_osrunning/delay_ostickspersec/delay_osintnesting�����궨��
// ����:delay_osschedlock/delay_osschedunlock/delay_ostimedly��������
// V1.8�޸�˵�� 20150519
// ����UCOSIII֧��ʱ��2��bug��
// delay_tickspersec��Ϊ��delay_ostickspersec
// delay_intnesting��Ϊ��delay_osintnesting
//////////////////////////////////////////////////////////////////////////////////

static u8 fac_us = 0;  // us��ʱ������
static u16 fac_ms = 0; // ms��ʱ������,��ucos��,����ÿ�����ĵ�ms��

#if SYSTEM_SUPPORT_OS // ���SYSTEM_SUPPORT_OS������,˵��Ҫ֧��OS��(������UCOS).
// ��delay_us/delay_ms��Ҫ֧��OS��ʱ����Ҫ������OS��صĺ궨��ͺ�����֧��
// ������3���궨��:
//     delay_osrunning:���ڱ�ʾOS��ǰ�Ƿ���������,�Ծ����Ƿ����ʹ����غ���
// delay_ostickspersec:���ڱ�ʾOS�趨��ʱ�ӽ���,delay_init�����������������ʼ��systick
//  delay_osintnesting:���ڱ�ʾOS�ж�Ƕ�׼���,��Ϊ�ж����治���Ե���,delay_msʹ�øò����������������
// Ȼ����3������:
//   delay_osschedlock:��������OS�������,��ֹ����
// delay_osschedunlock:���ڽ���OS�������,���¿�������
//     delay_ostimedly:����OS��ʱ,���������������.

// �����̽���UCOSII��UCOSIII��֧��,����OS,�����вο�����ֲ
// ֧��UCOSII
#ifdef OS_CRITICAL_METHOD					 // OS_CRITICAL_METHOD������,˵��Ҫ֧��UCOSII
#define delay_osrunning OSRunning			 // OS�Ƿ����б��,0,������;1,������
#define delay_ostickspersec OS_TICKS_PER_SEC // OSʱ�ӽ���,��ÿ����ȴ���
#define delay_osintnesting OSIntNesting		 // �ж�Ƕ�׼���,���ж�Ƕ�״���
#endif

// ֧��UCOSIII
#ifdef CPU_CFG_CRITICAL_METHOD				  // CPU_CFG_CRITICAL_METHOD������,˵��Ҫ֧��UCOSIII
#define delay_osrunning OSRunning			  // OS�Ƿ����б��,0,������;1,������
#define delay_ostickspersec OSCfg_TickRate_Hz // OSʱ�ӽ���,��ÿ����ȴ���
#define delay_osintnesting OSIntNestingCtr	  // �ж�Ƕ�׼���,���ж�Ƕ�״���
#endif

// us����ʱʱ,�ر��������(��ֹ���us���ӳ�)
void delay_osschedlock(void)
{
#ifdef CPU_CFG_CRITICAL_METHOD // ʹ��UCOSIII
	OS_ERR err;
	OSSchedLock(&err); // UCOSIII�ķ�ʽ,��ֹ���ȣ���ֹ���us��ʱ
#else				   // ����UCOSII
	OSSchedLock(); // UCOSII�ķ�ʽ,��ֹ���ȣ���ֹ���us��ʱ
#endif
}

// us����ʱʱ,�ָ��������
void delay_osschedunlock(void)
{
#ifdef CPU_CFG_CRITICAL_METHOD // ʹ��UCOSIII
	OS_ERR err;
	OSSchedUnlock(&err); // UCOSIII�ķ�ʽ,�ָ�����
#else					 // ����UCOSII
	OSSchedUnlock(); // UCOSII�ķ�ʽ,�ָ�����
#endif
}

// ����OS�Դ�����ʱ������ʱ
// ticks:��ʱ�Ľ�����
void delay_ostimedly(u32 ticks)
{
#ifdef CPU_CFG_CRITICAL_METHOD
	OS_ERR err;
	OSTimeDly(ticks, OS_OPT_TIME_PERIODIC, &err); // UCOSIII��ʱ��������ģʽ
#else
	OSTimeDly(ticks); // UCOSII��ʱ
#endif
}

// systick�жϷ�����,ʹ��ucosʱ�õ�
void SysTick_Handler(void)
{
	if (delay_osrunning == 1) // OS��ʼ����,��ִ�������ĵ��ȴ���
	{
		OSIntEnter(); // �����ж�
		OSTimeTick(); // ����ucos��ʱ�ӷ������
		OSIntExit();  // ���������л����ж�
	}
}
#endif

// ��ʼ���ӳٺ���
// ��ʹ��OS��ʱ��,�˺������ʼ��OS��ʱ�ӽ���
// SYSTICK��ʱ�ӹ̶�ΪHCLKʱ�ӵ�1/8
// SYSCLK:ϵͳʱ��
void delay_init()
{
#if SYSTEM_SUPPORT_OS // �����Ҫ֧��OS.
	u32 reload;
#endif
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); // ѡ���ⲿʱ��  HCLK/8
	fac_us = SystemCoreClock / 8000000;					  // Ϊϵͳʱ�ӵ�1/8
#if SYSTEM_SUPPORT_OS									  // �����Ҫ֧��OS.
	reload = SystemCoreClock / 8000000;					  // ÿ���ӵļ������� ��λΪK
	reload *= 1000000 / delay_ostickspersec;			  // ����delay_ostickspersec�趨���ʱ��
														  // reloadΪ24λ�Ĵ���,���ֵ:16777216,��72M��,Լ��1.86s����
	fac_ms = 1000 / delay_ostickspersec;				  // ����OS������ʱ�����ٵ�λ

	SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; // ����SYSTICK�ж�
	SysTick->LOAD = reload;					   // ÿ1/delay_ostickspersec���ж�һ��
	SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;  // ����SYSTICK

#else
	fac_ms = (u16)fac_us * 1000; // ��OS��,����ÿ��ms��Ҫ��systickʱ����
#endif
}

#if SYSTEM_SUPPORT_OS // �����Ҫ֧��OS.
// ��ʱnus
// nusΪҪ��ʱ��us��.
void delay_us(u32 nus)
{
	u32 ticks;
	u32 told, tnow, tcnt = 0;
	u32 reload = SysTick->LOAD; // LOAD��ֵ
	ticks = nus * fac_us;		// ��Ҫ�Ľ�����
	tcnt = 0;
	delay_osschedlock(); // ��ֹOS���ȣ���ֹ���us��ʱ
	told = SysTick->VAL; // �ս���ʱ�ļ�����ֵ
	while (1)
	{
		tnow = SysTick->VAL;
		if (tnow != told)
		{
			if (tnow < told)
				tcnt += told - tnow; // ����ע��һ��SYSTICK��һ���ݼ��ļ������Ϳ�����.
			else
				tcnt += reload - tnow + told;
			told = tnow;
			if (tcnt >= ticks)
				break; // ʱ�䳬��/����Ҫ�ӳٵ�ʱ��,���˳�.
		}
	};
	delay_osschedunlock(); // �ָ�OS����
}
// ��ʱnms
// nms:Ҫ��ʱ��ms��
void delay_ms(u16 nms)
{
	if (delay_osrunning && delay_osintnesting == 0) // ���OS�Ѿ�������,���Ҳ������ж�����(�ж����治���������)
	{
		if (nms >= fac_ms) // ��ʱ��ʱ�����OS������ʱ������
		{
			delay_ostimedly(nms / fac_ms); // OS��ʱ
		}
		nms %= fac_ms; // OS�Ѿ��޷��ṩ��ôС����ʱ��,������ͨ��ʽ��ʱ
	}
	delay_us((u32)(nms * 1000)); // ��ͨ��ʽ��ʱ
}
#else // ����OSʱ
// ��ʱnus
// nusΪҪ��ʱ��us��.
void delay_us(u32 nus)
{
	u32 temp;
	SysTick->LOAD = nus * fac_us;			  // ʱ�����
	SysTick->VAL = 0x00;					  // ��ռ�����
	SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // ��ʼ����
	do
	{
		temp = SysTick->CTRL;
	} while ((temp & 0x01) && !(temp & (1 << 16))); // �ȴ�ʱ�䵽��
	SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;		// �رռ�����
	SysTick->VAL = 0X00;							// ��ռ�����
}
// ��ʱnms
// ע��nms�ķ�Χ
// SysTick->LOADΪ24λ�Ĵ���,����,�����ʱΪ:
// nms<=0xffffff*8*1000/SYSCLK
// SYSCLK��λΪHz,nms��λΪms
// ��72M������,nms<=1864
void delay_ms(u16 nms)
{
	u32 temp;
	SysTick->LOAD = (u32)nms * fac_ms;		  // ʱ�����(SysTick->LOADΪ24bit)
	SysTick->VAL = 0x00;					  // ��ռ�����
	SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; // ��ʼ����
	do
	{
		temp = SysTick->CTRL;
	} while ((temp & 0x01) && !(temp & (1 << 16))); // �ȴ�ʱ�䵽��
	SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;		// �رռ�����
	SysTick->VAL = 0X00;							// ��ռ�����
}
#endif
